#include "../include/tcp_connection.h"
#include <boost/endian.hpp>
#include <iostream>
#include "../include/logical_pool.h"
#include "../include/user_list_manger.h"
tcp_connection::tcp_connection(boost::asio::io_context &_io_context):_socket(_io_context)
{
   //对socket进行初始化，放在指定的io_context里循环

   is_sending=false;
   is_close=false;
}

tcp_connection::~tcp_connection(){
    std::cout<<"成功释放一个tcp_connection连接！！"<<std::endl;

    //这里是待发送队列的清空操作
    while(!send_list.empty()){
        delete send_list.front().second;
        send_list.pop_front();
    }

    //从全局的user_list_manger中移除本连接----放在这里出问题，析构不能调用shared_from_this()

}



void tcp_connection::async_read_head()
{
    auto self=shared_from_this();
    
    //这里通过head_buffer来限制长度
    boost::asio::async_read(_socket,boost::asio::buffer(head_buffer),[self](boost::system::error_code ec, std::size_t len){
        if(!ec){
            //解析buffer里的数据--转为本机字节序
            std::cout<<"验证长度是否为HEAD_LEN"<<len<<std::endl;
            struct msg_head *head=(struct msg_head *)self->head_buffer;
            self->now_message_id=boost::endian::big_to_native(head->message_id);
            self->now_body_len=boost::endian::big_to_native(head->body_len);
            self->async_read_body();
        }else{
            std::cout<<"读取包头出错: "<<ec.what()<<std::endl;
            user_list_manger::get_instance()->remove_tcp_connection(self->email);
        }
        return;
    });


}

void tcp_connection::async_read_body()
{
    //根据长度去创建body长度
    body_buffer=new char[now_body_len];
    auto self=shared_from_this();
    boost::asio::async_read(_socket,
        boost::asio::buffer(body_buffer,now_body_len),
        boost::asio::transfer_exactly(now_body_len),
        [self](boost::system::error_code ec, std::size_t len){
            if(!ec){
                std::cout<<"验证长度是否为now_body_len"<<len<<std::endl;
                //组装一个
                struct full_msg *_full_msg=new struct full_msg;
                _full_msg->message_id=self->now_message_id;
                _full_msg->body_len=self->now_body_len;
                _full_msg->body=self->body_buffer;
                _full_msg->tcp_con=self;

                self->body_buffer=nullptr;  //清空本地数据缓存，交由_full_msg管控


                //可以交给专门的线程处理函数处理--如果较为费时的操作，不然可以考虑这里执行完
                //但是如何判断一个请求是否耗时呢？
                logical_pool::get_instance()->post_task(_full_msg);

                
                //然后
                self->async_read_head();
            }else{
                user_list_manger::get_instance()->remove_tcp_connection(self->email);
            }

        });
        

}

void tcp_connection::async_write_msg(u_short message_id, u_short body_len,const char *body)
{
    //将对应的数据转为网络字节序，并填充
    if(is_close==true){
        return;
    }
    

    u_short net_message_id=boost::endian::native_to_big(message_id);
    u_short net_body_len=boost::endian::native_to_big(body_len);
    
    //组装好后加锁放入对应的list中
    u_short true_len=sizeof(net_message_id)+sizeof(net_body_len)+body_len;
    char *full_package=new char[true_len];
    memcpy(full_package,&net_message_id,sizeof(net_message_id));
    memcpy(full_package+sizeof(net_message_id),&net_body_len,sizeof(net_body_len));
    memcpy(full_package+sizeof(net_message_id)+sizeof(net_message_id),body,body_len);
    
    bool excepted=false;
    bool desired=true;
    //为了避免极端情况下，两个消息同时发送，通过cas原子操作保证原子性
    if(is_sending.compare_exchange_strong(excepted,desired)){
       
        doing_send_pkg(std::make_pair(true_len,full_package));
        return;

    }else{
        excepted=false;
        send_list_mtx.lock();
        send_list.push_back(std::make_pair(true_len,full_package));
        send_list_mtx.unlock();
    }


    //继续判断状态---如果doing_send_pkg先获得锁,置为了false再往里插入数据，那么走到这里就可以继续回包，避免包发送不及时或无法发送
    if(is_sending.compare_exchange_strong(excepted,desired)){
        //这里原封不动弹出来
        send_list_mtx.lock();
        send_list.pop_front();
        send_list_mtx.unlock();
        doing_send_pkg(std::make_pair(true_len,full_package));
    }



}

boost::asio::ip::tcp::socket &tcp_connection::get_socket()
{
    return this->_socket;
    // TODO: 在此处插入 return 语句
}


void tcp_connection::doing_send_pkg(std::pair<u_short,const char *> _pair)
{
    // send_list_mtx.lock();
    // auto pair=send_list.front();
    // send_list.pop_front();
    // send_list_mtx.unlock();

    auto self=shared_from_this();
    
    boost::asio::async_write(_socket,
        boost::asio::buffer(_pair.second,_pair.first),[self,_pair](boost::system::error_code ec,
            std::size_t len){
                
                if(!ec){
                    std::cout<<"成功回报长度"<<len<<"预计回包长度"<<_pair.first<<std::endl;
                    delete _pair.second;
                    //这里继续加锁
                    self->send_list_mtx.lock();
                    if(self->send_list.size()>0){
                        auto send_list_item=self->send_list.front();
                        self->send_list.pop_front();
                        self->send_list_mtx.unlock();
                        self->doing_send_pkg(send_list_item);
                    }else{
                        self->is_sending=false;
                        self->send_list_mtx.unlock();
                    }

                }else{

                    self->is_close=true;
                    self->is_sending=false;
                    delete _pair.second;
                    std::cout<<"send_pkg error"<<ec.what()<<std::endl;
                    

                }

            });


}

